'''
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with self work for additional information
 * regarding copyright ownership.  The ASF licenses self file
 * to you under the Apache License, Version 2.0 (the
 * "License") you may not use self file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http:#www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
'''
from base.graph.NodeFactory import NodeFactory
from base.rdf.Container import Container
from base.rdf.impl.ContNodeIteratorFactoryImpl import ContNodeIteratorFactoryImpl
from base.rdf.impl.LiteralImpl import LiteralImpl
from base.rdf.impl.ResourceImpl import ResourceImpl
from base.shared.JenaException import JenaException
from base.vocabulary.RDF import RDF

#import java.util.*;

#import org.apache.jena.enhanced.*;
#import org.apache.jena.graph.*;
#import org.apache.jena.rdf.model.*;
#import org.apache.jena.shared.*;
#import org.apache.jena.vocabulary.RDF;

'''
 * An internal class not normally of interest to application developers.
 * A base class on which the other containers are built.
'''
iteratorFactory = ContNodeIteratorFactoryImpl()

class ContainerImpl(ResourceImpl, Container):

    '''
     * Creates ContainerImpl
    '''
    # param ModelCom model:
    def __init__(self):
        super().__init__()

    def initWithModelCom(self, model):
        super().initWithModelCom(model)
        return self

    # param String uri, ModelCom model:
    def initWithUriAndModelCom(self, uri, model):
        super().initWithUriAndModelCom(uri, model)
        return self
    

    # param Resource r, ModelCom model:
    def initWithResourceAndModelCom(self, r, model):
        super().initWithResourceAndModelCom(r.asNode(), model)
        return self
    

    # param Node n, EnhGraph g:
    def initWithNodeAndEnhGraph(self, n, g):
        super().initWithNodeAndEnhGraph(n, g)
        return self
    

    # protected ContainerImpl(Resource r):
    #     self(r, (ModelCom) r.getModel())
    

    # param Resource r
    # result boolean
    def isResource(self, r):
        return self.hasProperty(RDF.type, r)
    

    # @Override
    # param 
    # result boolean
    def isAlt(self):
        return self.isResource(RDF.Alt)
    

    # @Override
    # param 
    # result boolean
    def isBag(self):
        return self.isResource(RDF.Bag)
    

    # @Override
    # param 
    # result boolean
    def isSeq(self):
        return self.isResource(RDF.Seq)
    

    # @Override
    # param RDFNode n
    # result Container
    def add(self, n):
        i = self.size()
        self.addProperty(RDF.li(i + 1), n)
        return self
    

    # @Override
    # param boolean o
    # result Container
    def addPrimitive(self, o):
        return self.add(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param long o
    # result Container
    # def add(self, o):
    #     return add(getModel().createTypedLiteral(o))
    

    # @Override
    # param char o
    # result Container
    # def add(self, o):
    #     return add(getModel().createTypedLiteral(o))
    

    # @Override
    # param float o
    # result Container
    # def add(self, o):
    #     return add(getModel().createTypedLiteral(o))
    

    # @Override
    # param double o
    # result Container
    # def add(self, o):
    #     return add(getModel().createTypedLiteral(o))
    

    # @Override
    # param Object o
    # result Container
    # def add(self, o):
    #     return add(getModel().createTypedLiteral(o))
    

    # @Override
    # param String o
    # result Container
    # def add(self, o):
    #     return add(o, "")
    

    # @Override
    # param String o, String l
    # result Container
    # def add(self, o, l):
    #     return add(literal(o, l))
    

    # @Override
    # param RDFNode n
    # result boolean
    def contains(self, n):
        return self.containerContains(n)
    

    # @Override
    # param boolean o
    # result boolean
    # def contains(self, o):
    #     return contains(getModel().createTypedLiteral(o))
    #
    #
    # # @Override
    # # param long o
    # # result boolean
    # def contains(self, o):
    #     return contains(getModel().createTypedLiteral(o))
    #
    #
    # # @Override
    # # param char o
    # # result boolean
    # def contains(self, o):
    #     return contains(getModel().createTypedLiteral(o))
    #
    #
    # # @Override
    # # param float o
    # # result boolean
    # def contains(self, o):
    #     return contains(getModel().createTypedLiteral(o))
    #
    #
    # # @Override
    # # param double o
    # # result boolean
    # def contains(self, o):
    #     return contains(getModel().createTypedLiteral(o))
    #
    #
    # # @Override
    # # param Object o
    # # result boolean
    # def contains(self, o):
    #     return contains(getModel().createTypedLiteral(o))
    #
    #
    # # @Override
    # # param String o
    # # result boolean
    # def contains(self, o):
    #     return contains(o, "")
    #
    #
    # # @Override
    # # param String o, String l
    # # result boolean
    # def contains(self, o, l):
    #     return contains(literal(o, l))
    

    # param String s, String lang
    # result Literal
    def literal(self, s, lang):
        return LiteralImpl(NodeFactory.createLiteral(s, lang), self.getModelCom())
    

    # @Override
    # param 
    # result NodeIterator
    def iterator(self):
        return self.listContainerMembers(iteratorFactory)
    

    # @Override
    # param 
    # result int
    def size(self):
        result = 0
        # StmtIterator
        ite = self.listProperties()
        while (ite.hasNext()):
            if (ite.nextStatement().getPredicate().getOrdinal() != 0): result += 1
        ite.close()
        return result
    

    # @Override 继承原来的ContainerI
    # param Statement s
    # result Container
    def remove(self, s):
        size = self.size()
        # Statement last = null
        if (s.getPredicate().getOrdinal() == size):       # if last
            self.getModel().remove(s)
        else:
            last = self.getModel().getRequiredProperty(self, RDF.li(size))
            s.changeObject(last.getObject())
            self.getModel().remove(last)
        
        if (self.size() != (size - 1)):
            raise JenaException("container size")
        return self
    

    # @Override
    # param int index, RDFNode object
    # result Container
    def removeByIndexAndObject(self, index, object):
        self.remove(self.getModel().createStatement(self, RDF.li(index), object))
        return self
    

    '''
     * Answer an iterator over the members of self container.
     *
     * @param f the factory for constructing the final iterator
     * @return the member iterator
    '''
    # param NodeIteratorFactory f
    # result NodeIterator
    def listContainerMembers(self, f):
        # StmtIterator
        ite = self.listProperties()
        # Vector<Statement> result = Vector<>()
        # # int
        # maxOrdinal = 0
        # while (ite.hasNext()):
        #     # Statement
        #     stmt = ite.nextStatement()
        #     # int
        #     ordinal = stmt.getPredicate().getOrdinal()
        #     if (ordinal != 0):
        #         if (ordinal > maxOrdinal):
        #             maxOrdinal = ordinal
        #             result.setSize(ordinal)
        #
        #         result.setElementAt(stmt, ordinal - 1)
        #
        #
        # ite.close()
        # return f.createIterator(result.iterator(), result, self)
    

    # param RDFNode n
    # result int
    def containerIndexOf(self, n):
        result = 0
        # StmtIterator
        ite = self.listProperties()
        while (ite.hasNext()):
            # Statement
            stmt = ite.nextStatement()
            # int
            ordinal = stmt.getPredicate().getOrdinal()
            if (ordinal != 0 and n.equals(stmt.getObject())):
                result = ordinal
                break
            
        
        ite.close()
        return result
    

    # param RDFNode n
    # result boolean
    def containerContains(self, n):
        return self.containerIndexOf(n) != 0
    


